# app/services/question_matcher.py
import re
from app.services.ocr.utils.similarity import similar
from app.services.ocr.utils.text_processing import extract_question_rich, extract_ocr_options, normalize
from app.services.ocr.utils.utils import convert_to_numbers
from app.services.ocr_engine.ai_model import search_with_ai


class QuestionMatcher:
    @staticmethod
    def match(ocr_text,file_path):
        results = search_with_ai(ocr_text,file_path)
        question_stem = extract_question_rich(ocr_text)
        ocr_options_text, ocr_options = extract_ocr_options(ocr_text)
        return_results = []
        for ret in results:
            subject = ret.get('subject', '')
            if not subject:
                continue
            sim_score = similar(subject, question_stem.replace('N:错误Y:正确', ''))

            if ret.get('type_text') == '判断题':
                if ret.get('noVerify') or sim_score >= 0.8:
                    return_results.append(ret)
                continue

            if sim_score < 0.8:
                continue

            db_options = [ret.get(opt, '') for opt in ['optionA', 'optionB', 'optionC', 'optionD']]
            match_count = QuestionMatcher.count_option_match(ocr_options_text, db_options)

            if match_count >= 3:
                # ret = QuestionMatcher.fill_answer_letters(ret, db_options, ocr_options)
                return [ret]
            else:
                if sim_score >= 0.95:
                    return_results.append(ret)

        if not return_results:
            return_results = [r for r in results if r.get('noVerify')]

        return return_results

    @staticmethod
    def count_option_match(ocr_opts, db_opts):
        match_count = 0
        for index, ocr_opt in enumerate(ocr_opts):
            similarities = [similar(ocr_opt, db_opt) for db_opt in db_opts if db_opt]
            if not similarities:
                continue
            max_sim = max(similarities)
            if max_sim >= 0.7 or (index == len(ocr_opts) - 1 and max_sim >= 0.5):
                match_count += 1
        return match_count

    @staticmethod
    def fill_answer_letters(ret, db_options, ocr_options):
        ret['option'] = [f"{letter}:{normalize(text)}" for letter, text in ocr_options]

        if len(ret['option'][2]) <= 2:
            return ret

        correct_answer_str = convert_to_numbers(ret.get("answer", ""))
        if ',' in correct_answer_str:
            answer_parts = [int(x.strip()) - 1 for x in correct_answer_str.split(',') if x.strip().isdigit()]
        else:
            answer_parts = [int(x) - 1 for x in correct_answer_str if x.isdigit()]

        final_answer = []
        for pos in answer_parts:
            if 0 <= pos < len(db_options):
                correct_text = db_options[pos]
                matched_letter = ""
                max_sim = 0
                for letter, ocr_text in ocr_options:
                    sim = similar(normalize(ocr_text), correct_text)
                    if sim > max_sim:
                        max_sim = sim
                        matched_letter = letter.replace(':', '').replace('：', '').replace(' ', '')
                if max_sim >= 0.7:
                    final_answer.append(matched_letter)

        ret['answerLetter'] = final_answer
        return ret
